//------------------------------------------------------------------------------
//  <copyright file="KukaLBR4NativeTests.h" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//  </copyright>
//------------------------------------------------------------------------------

#pragma once 

#include "stdafx.h"
#include "KukaLBR4NativeTestLibImportExport.h"
#include "MockFRIConnection.h"
#include "TestPokeFRIConnection.h"
#include "TestResultStringCommon.h"

#include <ClientMessages.h>
#include <ControllerClientMessageHandler.h>
#include <ControllerStateMachineDescription.cs>
#include <ControllerStateMachineRegisters.h>
#include <IFRIConnection.h>
#include <KukaLBR4Definitions.h>
#include <KukaLBR4Operations.h>
#include <RegisterExchange.h>

// Throws an exception (unhandled) if the condition 'e' is not true.
// When called by a VS test method, generates a test failure if 
// the asserted condition fails.
#define KUKALBR4NATIVEASSERT(e, msg) if (!(e)) throw msg;

/// <summary> Joint angle targets used in tests. </summary>
const double pPokeJointAngleTarget[NUM_JOINTS] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7};

// This class is exported from the Microsoft.Robotics.Hardware.KukaLBR.KukaLBRNativeTests.dll
class KukaLBR4NativeTests : public TestResultStringCommon
{
public:
	/// <summary> Test exchange of register values using the <c>RegisterExchange</c> class. </summary>
	static void RegisterExchangeTest();

	/// <summary>  Just ensure that we don't wind up in the weeds if many CSMDs are sent rapidly </summary>
	static void TestSettingCsmd();

	/// <summary> Test that a hypotetical "poke" CSMD behaves as expected. </summary>
	static void PokeTest();

	/// <summary>
	/// Performs a sanity check that passing native tests actually passes.
	/// If this fails it is likely a test infra issue.
	/// </summary>
	static void NativeTestSanityCheckPassing();

	/// <summary> Performs a sanity check that failing native tests actually fails.  If this fails it is likely a test infra issue. </summary>
	static void NativeTestSanityCheckFailing();

private:
	/// <summary> Configure a set of registers with known values for testing. </summary>
	/// <param name="ppRegisters">
	/// Register to configure.  Assumption is that at least 3 registers
	/// are allocated with lengths of at least 1, 2, and 3 respectively.
	/// </param>
	static void ConfigureRegistersWithDefaultValues(double **ppRegisters);

	/// <summary> Asserts that a set of registers have the default values </summary>
	/// <param name="ppRegisters">
	/// Registers to confirm values of.  Assumption is that at least 3 registers
	/// are allocated with length of at least 1, 2, and 3 respectively.
	/// </param>
	static void AssertRegistersDefaultValues(double **ppRegisters);

	/// <summary> Generates a controller state machine for tests. </summary>
	static ControllerStateMachineDescription GenerateCsmd1();

	/// <summary>
	/// Generate a csmd that executes a poke -- i.e. does position control until it encounters
	/// a force in the environment along it's TCP's Z axis, then stops.
	/// </summary>
	static ControllerStateMachineDescription GeneratePokeCsmd();

	/// <summary>
	/// Generate a sequence of messages to IO thread that constantly reset the controller
	/// state machine description.
	/// <summary>
	/// <param name="message"> Pointer to the <c>MessageDescription</c> struct to initialize. </param>
	/// <param name="maxParameterSize"> Size of the parameter buffer allocated for <c>message->parameters</c>. </param>
	static void SendTestSettingCsmdMessages(ControllerClientMessageHandler *pMsgHandler);

	/// <summary>
	/// Send a sequence of messages to the ControllerClientMessageHandler
	/// corresponding to a "poke" action, and check that proper feedback is received.
	/// </summary>
	/// <param name="pMsgHandler"> The ControllerclientMessagehandler to interact with. </param>
	/// <param name="pFRIConnection"> The mock FRI connection that pMsgHandler was initialized with. </param>
	static void SendPokeTestMessages(ControllerClientMessageHandler *pMsgHandler, TestPokeFRIConnection *pFRIConnection);
};

/// <summary> Test exchange of register values using the <c>RegisterExchange</c> class. </summary>
/// <param name="resultString"> buffer for a failure message or indication that test passed. </param>
/// <param name="buffersize"> length of <c>resultString</c> buffer. </param>
extern "C" KUKALBR4NATIVETESTS_API void RegisterExchangeTest(char *resultString, int bufferSize);

/// <summary> Test that a hypotetical "poke" CSMD behaves as expected. </summary>
/// <param name="resultString"> buffer for a failure message or indication that test passed. </param>
/// <param name="buffersize"> length of <c>resultString</c> buffer. </param>
extern "C" KUKALBR4NATIVETESTS_API void PokeTest(char *resultString, int bufferSize);

/// <summary>  Just ensure that we don't wind up in the weeds if many CSMDs are sent rapidly </summary>
/// <param name="resultString"> buffer for a failure message or indication that test passed. </param>
/// <param name="buffersize"> length of <c>resultString</c> buffer. </param>
extern "C" KUKALBR4NATIVETESTS_API void TestSettingCsmd(char *resultString, int bufferSize);

/// <summary>
/// Performs a sanity check that passing native tests actually passes.
/// If this fails it is likely a test infra issue.
/// </summary>
/// <param name="resultString"> buffer for a failure message or indication that test passed. </param>
/// <param name="buffersize"> length of <c>resultString</c> buffer. </param>
extern "C" KUKALBR4NATIVETESTS_API void NativeSanityCheckPassing(char *resultString, int bufferSize);

/// <summary>
/// Performs a sanity check that passing native tests actually fails.
/// If this fails it is likely a test infra issue.
/// </summary>
/// <param name="resultString"> buffer for a failure message or indication that test passed. </param>
/// <param name="buffersize"> length of <c>resultString</c> buffer. </param>
extern "C" KUKALBR4NATIVETESTS_API void NativeSanityCheckFailing(char *resultString, int bufferSize);
